<template>
  <div class="nodes-content">
    <el-card class="nodes-container" shadow="hover">
      <template #header>
        <div class="card-header">
          <div>
            <h3>知识森林视图</h3>
          </div>
          <el-icon size="32" color="#9f8eaf"><Connection /></el-icon>
        </div>

<div class="breadcrumb-nav" v-if="props.currentCategory?.categoryName">
  <el-breadcrumb separator="/">
    <el-breadcrumb-item @click="router.push('/Knowledge')" class="breadcrumb-link">
      <el-icon><House /></el-icon>
      技术方向
    </el-breadcrumb-item>
    <el-breadcrumb-item class="current-category">
      {{ props.currentCategory.icon }} {{ props.currentCategory.categoryName }}
    </el-breadcrumb-item>
  </el-breadcrumb>
</div>
    </template>

      <!-- 操作栏 -->
      <div class="nodes-operations">
        <div class="search-filters-row">
          <el-input
            v-model="searchTerm"
            placeholder="搜索知识点..."
            class="search-input"
            size="large"
            @input="handleSearchDebounced"
          >
            <template #prefix>
              <el-icon><Search /></el-icon>
            </template>
          </el-input>

          <el-select 
            v-model="selectedDifficulty" 
            placeholder="难度筛选"
            class="filter-select"
            size="large"
            @change="handleFilterChange"
          >
            <el-option label="所有难度" value="all" />
            <el-option label="⭐ 初级" :value="1" />
            <el-option label="⭐⭐ 中级" :value="2" />
            <el-option label="⭐⭐⭐ 高级" :value="3" />
            <el-option label="⭐⭐⭐⭐ 专家" :value="4" />
            <el-option label="⭐⭐⭐⭐⭐ 大师" :value="5" />
          </el-select>
        </div>
        
        <el-button 
          type="primary" 
          @click="openModal('add')"
          size="large"
          class="add-btn"
        >
          <el-icon><Plus /></el-icon>
          <span>新增知识点</span>
        </el-button>
      </div>

      <!-- 加载状态 -->
      <div v-if="loading" class="loading-container">
        <el-skeleton :rows="6" animated>
          <template #template>
            <div class="skeleton-grid">
              <div v-for="i in 6" :key="i" class="skeleton-card">
                <div class="skeleton-header">
                  <el-skeleton-item variant="circle" style="width: 52px; height: 52px" />
                  <div class="skeleton-actions">
                    <el-skeleton-item variant="circle" style="width: 32px; height: 32px" />
                    <el-skeleton-item variant="circle" style="width: 32px; height: 32px" />
                  </div>
                </div>
                <div class="skeleton-content">
                  <el-skeleton-item variant="h3" style="width: 60%" />
                  <el-skeleton-item variant="text" style="width: 100%" />
                  <el-skeleton-item variant="text" style="width: 80%" />
                </div>
              </div>
            </div>
          </template>
        </el-skeleton>
      </div>

      <!-- 错误状态 -->
      <el-result
        v-else-if="error"
        icon="error"
        title="加载失败"
        :sub-title="error"
      >
        <template #extra>
          <el-button type="primary" @click="loadNodes">重新加载</el-button>
        </template>
      </el-result>

      <!-- 节点网格 -->
      <div v-else class="nodes-grid">
        <el-card 
          v-for="node in nodes" 
          :key="node.id"
          class="node-card"
          :class="{ 'node-card-hover': hoveredNode === node.id }"
          @mouseenter="hoveredNode = node.id"
          @mouseleave="hoveredNode = null"
          shadow="hover"
        >
          <div class="node-content">
            <div class="node-header">
              <div class="node-icon" :style="{ background: getDifficultyGradient(node.difficulty) }">
                <span class="node-icon-text">{{ getTypeIcon(node.type || node.nodeType) }}</span>
              </div>
              
              <div class="node-actions">
                <el-button circle size="small" class="edit-btn" @click="editNode(node)">
                  <el-icon><Edit /></el-icon>
                </el-button>
                <el-button circle size="small" class="delete-btn" @click="deleteNode(node)">
                  <el-icon><Delete /></el-icon>
                </el-button>
              </div>
            </div>
            
            <div class="node-info">
              <h4 class="node-title">{{ node.label || node.name }}</h4>
              
              <div class="node-tags">
                <el-tag size="small" :type="getTagType(node.type || node.nodeType)" effect="plain">
                  {{ getTypeLabel(node.type || node.nodeType) }}
                </el-tag>
                <el-tag size="small" type="warning" effect="plain">
                  {{ '⭐'.repeat(node.difficulty) }}
                </el-tag>
                <el-tag 
                  v-if="node.category" 
                  size="small" 
                  type="info" 
                  effect="plain"
                >
                 {{ getCategoryIcon(node) }} {{ getCategoryDisplayName(node) }}
                </el-tag>
              </div>
              
              <p v-if="node.description" class="node-description">
                {{ node.description }}
              </p>

              <div class="node-stats">
                <div class="node-stat">
                  <el-icon><User /></el-icon>
                  <span>{{ node.learners || 0 }}</span>
                </div>
                <div class="node-stat">
                  <el-icon><Connection /></el-icon>
                  <span>{{ node.connections || 0 }}</span>
                </div>
                <div class="node-stat">
                  <el-icon><View /></el-icon>
                  <span>{{ node.views || 0 }}</span>
                </div>
              </div>
            </div>
            
            <div class="node-progress">
              <div class="progress-info">
                <span>学习热度</span>
                <span>{{ Math.min(Math.round(((node.learners || 0) / 300) * 100), 100) }}%</span>
              </div>
              <el-progress 
                :percentage="Math.min(Math.round(((node.learners || 0) / 300) * 100), 100)" 
                :color="getDifficultyColor(node.difficulty)"
                :show-text="false"
                :stroke-width="10"
              />
            </div>

            <div class="node-footer">
              <div class="node-meta">
                <span class="create-time">
                  创建: {{ formatDate(node.createTime || node.created_at || node.createdAt) }}
                </span>
                <span class="update-time">
                  更新: {{ formatDate(node.updateTime || node.updated_at || node.updatedAt || node.lastModified) }}
                </span>
              </div>
            </div>
          </div>
        </el-card>
      </div>

      <!-- 空状态 -->
      <el-empty 
        v-if="!loading && !error && nodes.length === 0" 
        description="暂无知识点数据"
        :image-size="200"
      >
        <template #description>
          <p>{{ searchTerm ? '未找到匹配的知识点' : '暂无知识点数据' }}</p>
        </template>
        <el-button type="primary" @click="openModal('add')">
          {{ searchTerm ? '清除搜索' : '创建第一个知识点' }}
        </el-button>
      </el-empty>

      <!-- 分页 -->
      <div v-if="!loading && !error && totalCount > 0" class="pagination-container">
        <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :page-sizes="[6, 12, 24, 36, 48]"
          :total="totalCount"
          layout="total, sizes, prev, pager, next, jumper"
          background
          @current-change="handlePageChange"
          @size-change="handleSizeChange"
        />
      </div>
    </el-card>

    <!-- 知识点管理模态框 -->
    <el-dialog 
      v-model="showNodeModal" 
      :title="nodeModalTitle"
      class="custom-dialog"
      @close="resetForm"
    >
      <div class="modal-content">
        <el-form 
          ref="nodeFormRef"
          :model="nodeForm" 
          :rules="nodeFormRules"
          label-width="120px" 
          class="node-form"
        >
          <div class="form-row">
            <el-form-item label="节点名称" prop="name">
              <el-input v-model="nodeForm.name" placeholder="例如：React Hooks" />
            </el-form-item>
            <el-form-item label="节点标识" prop="nodeKey">
              <el-input v-model="nodeForm.nodeKey" placeholder="例如：react-hooks" />
            </el-form-item>
          </div>
          
          <div class="form-row">
            <el-form-item label="节点类型" prop="nodeType">
              <el-select v-model="nodeForm.nodeType" placeholder="选择节点类型">
                <el-option label="🏗️ 基础知识" value="foundation" />
                <el-option label="📦 框架" value="framework" />
                <el-option label="💡 概念" value="concept" />
                <el-option label="🔧 工具" value="tool" />
              </el-select>
            </el-form-item>
            <el-form-item label="难度等级" prop="difficulty">
              <el-select v-model="nodeForm.difficulty" placeholder="选择难度">
                <el-option 
                  v-for="level in [1,2,3,4,5]" 
                  :key="level" 
                  :label="`${'⭐'.repeat(level)} ${level}星`" 
                  :value="level" 
                />
              </el-select>
            </el-form-item>
          </div>

          <div class="form-row">
            <el-form-item label="总关卡数">
              <el-input-number v-model="nodeForm.totalStages" :min="1" :max="100" />
            </el-form-item>
            <el-form-item label="图标">
              <el-input v-model="nodeForm.icon" placeholder="例如：🎨" />
            </el-form-item>
          </div>
          
          <el-form-item label="描述" prop="description">
            <el-input 
              v-model="nodeForm.description" 
              type="textarea" 
              :rows="4"
              placeholder="描述这个知识点的内容、学习目标和应用场景..."
            />
          </el-form-item>
        </el-form>
      </div>
      
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeModal">取消</el-button>
          <el-button type="primary" @click="saveModal" :loading="modalLoading">
            {{ isEditMode ? '保存更新' : '创建' }}
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Connection, Search, Plus, Edit, Delete, User, View } from '@element-plus/icons-vue'
import { get, postJson } from '@/axios/index'
import { useRouter } from 'vue-router'  // 添加这个导入

// 添加 router
const router = useRouter()

// 在NodeManagement组件中
const props = defineProps({
  categories: Array,
  allNodes: Array,
  currentCategory: Object  // 新增：当前技术方向上下文
})


// Emits
const emit = defineEmits(['refresh-data'])

// 响应式数据
const searchTerm = ref('')
const selectedCategory = ref('all')
const selectedDifficulty = ref('all')
const hoveredNode = ref(null)
const currentPage = ref(1)
const pageSize = ref(12)
const loading = ref(false)
const error = ref('')

// 数据状态
const nodes = ref([])
const totalCount = ref(0)

// 知识点模态框相关状态
const showNodeModal = ref(false)
const modalLoading = ref(false)
const isEditMode = ref(false)
const editingNodeId = ref(null)

// 组件引用
const nodeFormRef = ref()

// 知识点表单数据
const nodeForm = reactive({
  name: '',
  nodeKey: '',
  nodeType: '',
  difficulty: 1,
  categories: [], // 改为数组，支持多个技术方向
  category: '',   // 保留单选字段，兼容简化使用
  description: '',
  estimatedTime: '',
  totalStages: 1,
  icon: ''
})


// 前端表单验证规则
const nodeFormRules = {
  name: [
    { required: true, message: '请输入节点名称', trigger: 'blur' },
    { min: 2, max: 50, message: '节点名称长度在 2 到 50 个字符', trigger: 'blur' },
    {
      validator: async (rule, value, callback) => {
        if (!value || value.trim() === '') {
          return callback();
        }
        
        try {
          const params = {
            field: 'name',
            value: value.trim()
          };
          
          // 确保在编辑模式下传递正确的ID
          if (isEditMode.value && editingNodeId.value) {
            params.id = editingNodeId.value;
            console.log('编辑模式校验，排除ID:', editingNodeId.value);
          } else {
            console.log('新增模式校验');
          }
          
          console.log('校验参数:', params);
          const response = await get('/knowledgeNode/checkUnique', params);
          console.log('校验响应:', response);
          
          // 修复：正确处理响应和错误消息
          if (response && response.data === true) {
            // data为true表示唯一，校验通过
            callback();
          } else {
            // data为false表示不唯一，校验失败
            const errorMsg = '该知识点名称已被使用，请换一个名称';
            callback(new Error(errorMsg));
          }
        } catch (error) {
          console.error('唯一性校验出错:', error);
          callback(new Error('校验失败，请重试'));
        }
      },
      trigger: 'blur'
    }
  ],
  nodeKey: [
    { required: true, message: '请输入节点标识', trigger: 'blur' },
    { pattern: /^[a-zA-Z0-9_-]+$/, message: '节点标识只能包含字母、数字、下划线和横线', trigger: 'blur' },
    {
      validator: async (rule, value, callback) => {
        if (!value || value.trim() === '') {
          return callback();
        }
        
        try {
          const params = {
            field: 'nodeKey',
            value: value.trim()
          };
          
          // 确保在编辑模式下传递正确的ID
          if (isEditMode.value && editingNodeId.value) {
            params.id = editingNodeId.value;
            console.log('编辑模式校验nodeKey，排除ID:', editingNodeId.value);
          } else {
            console.log('新增模式校验nodeKey');
          }
          
          console.log('nodeKey校验参数:', params);
          const response = await get('/knowledgeNode/checkUnique', params);
          console.log('nodeKey校验响应:', response);
          
          // 修复：正确处理响应和错误消息  
          if (response && response.data === true) {
            // data为true表示唯一，校验通过
            callback();
          } else {
            // data为false表示不唯一，校验失败
            const errorMsg = '该节点标识已被使用，请换一个标识';
            callback(new Error(errorMsg));
          }
        } catch (error) {
          console.error('nodeKey唯一性校验出错:', error);
          callback(new Error('校验失败，请重试'));
        }
      },
      trigger: 'blur'
    }
  ],
  nodeType: [
    { required: true, message: '请选择节点类型', trigger: 'change' }
  ],
  difficulty: [
    { required: true, message: '请选择难度等级', trigger: 'change' }
  ],
  description: [
    { required: true, message: '请输入描述', trigger: 'blur' },
    { min: 4, max: 500, message: '描述长度在 4 到 500 个字符', trigger: 'blur' }
  ]
}

// 计算属性
const nodeModalTitle = computed(() => {
  return isEditMode.value ? '编辑知识点' : '新增知识点'
})

// 防抖搜索
let searchTimeout = null
const handleSearchDebounced = () => {
  clearTimeout(searchTimeout)
  searchTimeout = setTimeout(() => {
    currentPage.value = 1
    loadNodes()
  }, 500)
}

// 筛选器变化处理
const handleFilterChange = () => {
  currentPage.value = 1
  loadNodes()
}

// 分页处理
const handlePageChange = (page) => {
  currentPage.value = page
  loadNodes()
}

const handleSizeChange = (size) => {
  pageSize.value = size
  currentPage.value = 1
  loadNodes()
}


// 从后端加载知识点数据
const loadNodes = async () => {
  loading.value = true
  error.value = ''
  
  try {
    const params = {
      pageNum: currentPage.value,
      pageSize: pageSize.value
    }

    // 添加搜索条件
    if (searchTerm.value && searchTerm.value.trim()) {
      params.searchTerm = searchTerm.value.trim()
    }

    // 添加难度筛选
    if (selectedDifficulty.value && selectedDifficulty.value !== 'all') {
      params.difficulty = selectedDifficulty.value
    }

        // 新增：如果有当前技术方向，自动筛选
    if (props.currentCategory?.categoryId) {
      params.category = props.currentCategory.categoryId
    } else if (props.currentCategory?.categoryKey) {
      params.category = props.currentCategory.categoryKey
    }

    const response = await get('/knowledgeNode/list', params)

  
    if (response) {
      if (response.data) {
        nodes.value = response.data.list || []
        totalCount.value = response.data.total || 0
        currentPage.value = response.data.pageNum || currentPage.value
      }
      else if (response.list) {
        nodes.value = response.list || []
        totalCount.value = response.total || 0
        currentPage.value = response.pageNum || currentPage.value
      }
      else if (Array.isArray(response)) {
        nodes.value = response
        totalCount.value = response.length
      } else {
        nodes.value = []
        totalCount.value = 0
      }
    }
  } catch (err) {
    error.value = err.message || '加载知识点数据失败'
    nodes.value = []
    totalCount.value = 0
  } finally {
    loading.value = false
  }
}

// 修改添加知识点方法，自动关联当前技术方向
const openModal = (mode, nodeData = null) => {
  if (mode === 'add') {
    // 重置表单并设置默认技术方向
    isEditMode.value = false
    editingNodeId.value = null
    resetForm()
    
    if (props.currentCategory?.categoryId) {
      nodeForm.category = props.currentCategory.categoryId
    } else if (props.currentCategory?.categoryKey) {
      nodeForm.category = props.currentCategory.categoryKey
    }
  } else if (mode === 'edit' && nodeData) {
    // 编辑模式
    isEditMode.value = true
    
    // 确保节点数据包含ID字段
    if (!nodeData.id) {
      ElMessage.error('节点数据缺少ID字段，无法编辑')
      return
    }
    
    try {
      if (typeof nodeData.id === 'number') {
        editingNodeId.value = nodeData.id
      } else if (typeof nodeData.id === 'string') {
        const numericId = parseInt(nodeData.id)
        if (!isNaN(numericId)) {
          editingNodeId.value = numericId
        } else {
          throw new Error('ID不是有效数字')
        }
      }
    } catch (e) {
      ElMessage.error('节点ID格式不正确，无法编辑')
      return
    }
    
    // 填充表单数据
    nodeForm.name = nodeData.label || nodeData.name || ''
    nodeForm.nodeKey = nodeData.nodeKey || ''
    nodeForm.nodeType = nodeData.type || nodeData.nodeType || ''
    nodeForm.difficulty = nodeData.difficulty || 1
    nodeForm.category = nodeData.category || nodeData.type || nodeData.nodeType || ''
    nodeForm.description = nodeData.description || ''
    nodeForm.estimatedTime = nodeData.estimatedTime || ''
    nodeForm.totalStages = nodeData.totalStages || 1
    nodeForm.icon = nodeData.icon || ''
  }
  
  showNodeModal.value = true
}

const closeModal = () => {
  showNodeModal.value = false
  resetForm()
}

const resetForm = () => {
  Object.assign(nodeForm, {
    name: '',
    nodeKey: '',
    nodeType: '',
    difficulty: 1,
    category: '',
    description: '',
    estimatedTime: '',
    totalStages: 1,
    icon: ''
  })
  
  // 清空表单验证
  nextTick(() => {
    if (nodeFormRef.value) {
      nodeFormRef.value.clearValidate()
    }
  })
  
  isEditMode.value = false
  editingNodeId.value = null
}

const saveModal = async () => {
  const valid = await nodeFormRef.value?.validate().catch(() => false)
  if (!valid) {
    ElMessage.warning('请检查表单填写是否完整/正确')
    return
  }
  
  modalLoading.value = true
  
  try {
    const formData = {
      name: nodeForm.name,
      nodeKey: nodeForm.nodeKey,
      nodeType: nodeForm.nodeType,
      difficulty: nodeForm.difficulty,

      category: nodeForm.category,
      description: nodeForm.description,
      estimatedTime: nodeForm.estimatedTime,
      totalStages: nodeForm.totalStages,
      icon: nodeForm.icon
    }

     // 添加调试日志
    console.log('=== 前端提交数据 ===')
    console.log('当前技术方向上下文:', props.currentCategory)
    console.log('表单category值:', nodeForm.category)
    console.log('完整提交数据:', formData)
    
    // 确保category不为空
    if (props.currentCategory && !formData.category) {
      formData.category = props.currentCategory.categoryId || props.currentCategory.categoryKey
      console.log('自动补充category:', formData.category)
    }
    
    let response
    if (isEditMode.value) {
    
      if (!editingNodeId.value) {
        throw new Error('编辑节点ID缺失')
      }
      
 
      response = await postJson(`/knowledgeNode/update/${editingNodeId.value}`, formData)
      console.log('知识点更新成功')
    } else {
      // 创建知识点  
      response = await postJson('/knowledgeNode/create', formData)
      console.log('知识点创建成功')
    }
    
    closeModal()
    await loadNodes()
    emit('refresh-data')
    
  } catch (error) {
    ElMessage.error(`${isEditMode.value ? '更新' : '创建'}知识点失败: ${error.message || '未知错误'}`)
  } finally {
    modalLoading.value = false
  }
}

const getCategoryDisplayName = (node) => {
  // 从node中获取技术方向信息
  const categoryKey = node.category || node.type || node.nodeType
  if (!categoryKey) return '未分类'
  
  // 在props.categories中查找对应的技术方向
  const category = props.categories?.find(cat => cat.categoryKey === categoryKey)
  return category ? category.categoryName : categoryKey
}

const getCategoryIcon = (node) => {
  const categoryKey = node.category || node.type || node.nodeType
  if (!categoryKey) return '📚'
  
  const category = props.categories?.find(cat => cat.categoryKey === categoryKey)
  return category ? category.icon : '📚'
}

// 工具方法
const getTypeIcon = (type) => {
  const icons = {
    foundation: '🏗️',
    framework: '📦', 
    concept: '💡',
    tool: '🔧',
    frontend: '🎨',
    backend: '⚙️',
    database: '🗄️',
    devops: '🚀',
    ai: '🤖',
    mobile: '📱'
  }
  return icons[type] || '📚'
}

const getTypeLabel = (type) => {
  const labels = {
    foundation: '基础知识',
    framework: '框架',
    concept: '概念',
    tool: '工具',
    frontend: '前端开发',
    backend: '后端开发',
    database: '数据库',
    devops: 'DevOps',
    ai: '人工智能', 
    mobile: '移动开发'
  }
  return labels[type] || '未知类型'
}

const getTagType = (type) => {
  const types = {
    foundation: 'success',
    framework: 'primary',
    concept: 'warning',
    tool: 'info',
    frontend: 'success',
    backend: 'primary',
    database: 'info',
    devops: 'warning',
    ai: 'danger',
    mobile: 'success'
  }
  return types[type] || 'info'
}

const getDifficultyGradient = (difficulty) => {
  const gradients = {
    1: 'linear-gradient(135deg, #d2dee5 0%, #bdcbd7 100%)',
    2: 'linear-gradient(135deg, #99b4cc 0%, #7393c6 100%)',
    3: 'linear-gradient(135deg, #9f8eaf 0%, #c5a7be 100%)',
    4: 'linear-gradient(135deg, #e8cadb 0%, #faf1f8 100%)',
    5: 'linear-gradient(135deg, #ac7c89 0%, #8c5e67 100%)'
  }
  return gradients[difficulty] || gradients[1]
}

const getDifficultyColor = (difficulty) => {
  const colors = {
    1: '#d2dee5',
    2: '#7393c6', 
    3: '#9f8eaf',
    4: '#e8cadb',
    5: '#ac7c89'
  }
  return colors[difficulty] || '#9f8eaf'
}

const formatDate = (dateString) => {
  if (!dateString) return '未知时间'
  try {
    // 处理多种日期格式
    let date
    if (typeof dateString === 'string') {
      // 处理 ISO 格式或其他字符串格式
      date = new Date(dateString.replace('T', ' ').replace('Z', ''))
    } else if (typeof dateString === 'number') {
      // 处理时间戳
      date = new Date(dateString)
    } else {
      date = new Date(dateString)
    }
    
    if (isNaN(date.getTime())) {
      return '未知时间'
    }
    
    return date.toLocaleDateString('zh-CN', {
      year: 'numeric',
      month: '2-digit', 
      day: '2-digit'
    })
  } catch (e) {
    return '未知时间'
  }
}

// 操作方法
// 编辑节点
const editNode = (node) => {
  openModal('edit', node)
}

// 删除节点
const deleteNode = (node) => {
  ElMessageBox.confirm(
    `确定要删除 "${node.label || node.name}" 知识点吗？此操作不可恢复。`,
    '删除确认',
    {
      confirmButtonText: '确定删除',
      cancelButtonText: '取消',
      type: 'warning',
    }
  ).then(async () => {
    try {
      ElMessage.info('删除功能暂时禁用，请联系管理员')
    } catch (err) {
      ElMessage.error('删除失败: ' + (err.message || '未知错误'))
    }
  }).catch(() => {
    // 用户取消删除操作
  })
}

// 暴露方法供父组件调用
defineExpose({
  loadNodes,
  openModal
})



// 在组件挂载时
onMounted(() => {
  loadNodes()
})


</script>

<style scoped>
/* 知识点管理容器 */
.nodes-container {
  background: white;
  border-radius: 16px;
  border: none;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  overflow: hidden;
}

.nodes-container :deep(.el-card__header) {
  background: linear-gradient(135deg, #faf8fc 0%, #f8fafc 100%);
  border-bottom: 1px solid #f1f5f9;
  padding: 24px 28px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-header h3 {
  font-size: 20px;
  font-weight: 700;
  color: #1e293b;
  margin: 0 0 4px 0;
}

.card-header p {
  color: #6b7280;
  margin: 0;
  font-size: 14px;
}

/* 操作栏优化 */
.nodes-operations {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 28px;
  align-items: center;
  padding: 0 4px;
}

.search-filters-row {
  display: flex;
  gap: 16px;
  flex: 1;
}

.search-input {
  flex: 1;
  min-width: 200px;
}

.search-input :deep(.el-input__wrapper) {
  border-radius: 12px;
  border: 1px solid #e8cadb;
  box-shadow: 0 2px 8px rgba(159, 142, 175, 0.08);
}

.search-input :deep(.el-input__wrapper):hover {
  border-color: #9f8eaf;
}

.filter-select {
  width: 160px;
}

.filter-select :deep(.el-input__wrapper) {
  border-radius: 12px;
  border: 1px solid #e8cadb;
}

.add-btn {
  background: linear-gradient(135deg, #9f8eaf 0%, #c5a7be 100%);
  border: none;
  border-radius: 12px;
  padding: 12px 24px;
  transition: all 0.3s ease;
  box-shadow: 0 4px 12px rgba(159, 142, 175, 0.25);
  white-space: nowrap;
}

.add-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(159, 142, 175, 0.35);
}

/* 加载状态样式 */
.loading-container {
  padding: 20px;
}

.skeleton-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 24px;
}

.skeleton-card {
  border: 1px solid #f1f5f9;
  border-radius: 16px;
  padding: 24px;
  background: linear-gradient(135deg, #faf8fc 0%, #f4f1f7 100%);
}

.skeleton-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 18px;
}

.skeleton-actions {
  display: flex;
  gap: 8px;
}

.skeleton-content {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* 节点网格优化 */
.nodes-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 24px;
  margin-bottom: 32px;
}

.node-card {
  border-radius: 16px;
  border: 1px solid #e8cadb;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
  height: 100%;
  /* 修改：添加灰紫色背景 */
  background: linear-gradient(135deg, #faf8fc 0%, #f4f1f7 100%);
  overflow: hidden;
}

.node-card:hover,
.node-card-hover {
  transform: translateY(-6px);
  box-shadow: 0 20px 40px rgba(159, 142, 175, 0.15);
  border-color: #c5a7be;
  /* 修改：hover时更深的灰紫色背景 */
  background: linear-gradient(135deg, #f8f5fb 0%, #f0ebf4 100%);
}

.node-content {
  padding: 24px;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.node-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 18px;
}

.node-icon {
  width: 52px;
  height: 52px;
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 22px;
  transition: transform 0.3s ease;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.node-card:hover .node-icon {
  transform: scale(1.1) rotate(5deg);
}

.node-actions {
  display: flex;
  gap: 8px;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.node-card:hover .node-actions {
  opacity: 1;
}

.node-actions .el-button {
  border: 1px solid rgba(255, 255, 255, 0.8);
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(10px);
}

/* 修改：编辑按钮浅草绿色 */
.edit-btn {
  background: linear-gradient(135deg, #a8e6a3 0%, #7dd87a 100%) !important;
  border: 1px solid #7dd87a !important;
  color: white !important;
}

.edit-btn:hover {
  background: linear-gradient(135deg, #7dd87a 0%, #5fb85c 100%) !important;
  border-color: #5fb85c !important;
  transform: scale(1.05);
}

/* 修改：删除按钮淡红色 */
.delete-btn {
  background: linear-gradient(135deg, #ffb3ba 0%, #ff8a95 100%) !important;
  border: 1px solid #ff8a95 !important;
  color: white !important;
}

.delete-btn:hover {
  background: linear-gradient(135deg, #ff8a95 0%, #ff6b7d 100%) !important;
  border-color: #ff6b7d !important;
  transform: scale(1.05);
}

.node-info {
  flex: 1;
  margin-bottom: 20px;
}

.node-title {
  font-size: 17px;
  font-weight: 700;
  margin: 0 0 14px 0;
  color: #1e293b;
  line-height: 1.4;
}

.node-tags {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}

.node-tags .el-tag {
  border-radius: 8px;
  font-weight: 500;
}

.node-description {
  color: #64748b;
  font-size: 14px;
  line-height: 1.6;
  margin: 0 0 16px 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.node-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin-top: 16px;
  padding: 12px;
  background: rgba(255, 255, 255, 0.6);
  border-radius: 10px;
  backdrop-filter: blur(5px);
}

.node-stat {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: #64748b;
  font-weight: 500;
}

.node-stat .el-icon {
  color: #9f8eaf;
}

.node-progress {
  margin-top: auto;
  padding-top: 16px;
}

.progress-info {
  display: flex;
  justify-content: space-between;
  margin-bottom: 10px;
  font-size: 13px;
  color: #64748b;
  font-weight: 500;
}

.node-progress :deep(.el-progress-bar__outer) {
  background: rgba(241, 245, 249, 0.8);
  border-radius: 10px;
}

.node-progress :deep(.el-progress-bar__inner) {
  border-radius: 10px;
}

.node-footer {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid rgba(248, 250, 252, 0.8);
}

.node-meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  color: #64748b;
  font-weight: 500;
}

.create-time,
.update-time {
  display: flex;
  align-items: center;
  gap: 4px;
}

.create-time::before {
  content: "📅";
  font-size: 10px;
}

.update-time::before {
  content: "🔄";
  font-size: 10px;
}

/* 分页样式 */
.pagination-container {
  margin-top: 32px;
  display: flex;
  justify-content: center;
}

.pagination-container :deep(.el-pagination) {
  --el-pagination-bg-color: #faf8fc;
  --el-pagination-text-color: #64748b;
  --el-pagination-border-radius: 8px;
}

/* 模态框表单样式 */
.modal-content {
  padding: 20px;
  max-height: 70vh;
  overflow-y: auto;
}

.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
  margin-bottom: 20px;
}

.node-form :deep(.el-form-item) {
  margin-bottom: 22px;
}

.node-form :deep(.el-form-item__label) {
  font-weight: 600;
  color: #374151;
  line-height: 1.5;
}

.node-form :deep(.el-input__wrapper) {
  border-radius: 8px;
  border: 1px solid #e8cadb;
  transition: all 0.3s ease;
}

.node-form :deep(.el-input__wrapper):hover {
  border-color: #9f8eaf;
}

.node-form :deep(.el-textarea__inner:focus) {
  border-color: #9f8eaf;
  box-shadow: 0 0 0 2px rgba(159, 142, 175, 0.1);
}

.node-form :deep(.el-select .el-input__wrapper) {
  border-radius: 8px;
  border: 1px solid #e8cadb;
}

.node-form :deep(.el-textarea__inner) {
  border-radius: 8px;
  border: 1px solid #e8cadb;
  transition: all 0.3s ease;
}

.node-form :deep(.el-textarea__inner:focus) {
  border-color: #9f8eaf;
  box-shadow: 0 0 0 2px rgba(159, 142, 175, 0.1);
}

.node-form :deep(.el-input-number) {
  width: 100%;
}

.node-form :deep(.el-input-number .el-input__wrapper) {
  border-radius: 8px;
}

.node-form :deep(.el-input__wrapper.is-focus) {
  border-color: #9f8eaf;
  box-shadow: 0 0 0 2px rgba(159, 142, 175, 0.1);
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

/* 调整模态框宽度和响应式 */
.custom-dialog {
  width: 90% !important;
  max-width: 800px !important;
  border-radius: 16px;
  overflow: hidden;
  margin: auto !important;
}

.custom-dialog :deep(.el-dialog__header) {
  background: linear-gradient(135deg, #faf8fc 0%, #f8fafc 100%);
  border-bottom: 1px solid #f1f5f9;
  padding: 20px 24px;
  border-radius: 16px 16px 0 0 !important;
  text-align: center;
}

.custom-dialog :deep(.el-dialog__title) {
  font-size: 18px;
  font-weight: 700;
  color: #1e293b;
}

.custom-dialog :deep(.el-dialog__body) {
  padding: 0;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .nodes-operations {
    flex-direction: column;
    align-items: stretch;
  }

  .search-input,
  .filter-select {
    width: 100%;
  }

  .nodes-grid {
    grid-template-columns: 1fr;
    gap: 16px;
  }

  .skeleton-grid {
    grid-template-columns: 1fr;
  }

  .custom-dialog {
    width: 95% !important;
    max-width: none !important;
    margin-top: 20px;
  }
  
  .form-row {
    grid-template-columns: 1fr;
    gap: 15px;
  }
  
  .modal-content {
    padding: 15px;
  }
  
  .node-form :deep(.el-form-item__label) {
    font-size: 14px;
  }
  
  .dialog-footer {
    padding: 15px;
    flex-direction: column;
  }
  
  .dialog-footer .el-button {
    width: 100%;
  }
}

@media (max-width: 480px) {
  .custom-dialog {
    width: 98% !important;
    margin-left: 1%;
    margin-right: 1%;
  }
  
  .node-form :deep(.el-form-item__label) {
    text-align: left;
    padding-bottom: 5px;
  }
  
  .node-form :deep(.el-form-item__content) {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* 错误结果样式 */
:deep(.el-result) {
  padding: 40px 20px;
}

:deep(.el-result__title) {
  color: #1e293b;
  font-weight: 600;
}

:deep(.el-result__subtitle) {
  color: #64748b;
}

.breadcrumb-nav {
  margin-bottom: 16px;
  padding: 12px 16px;
  background: rgba(159, 142, 175, 0.05);
  border-radius: 8px;
  border-left: 3px solid #9f8eaf;
}

.breadcrumb-link {
  cursor: pointer;
  color: #9f8eaf;
  transition: all 0.3s ease;
}

.breadcrumb-link:hover {
  color: #7d6b8a;
}

.current-category {
  font-weight: 600;
  color: #1e293b;
}
</style>